/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package philosofer;

/**
 *
 * @author otaviokz
 */
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Philosofer {

    private static ObjectOutputStream output;
    private static ObjectInputStream input;
    private static String message;
    private static String name;
    private static String serverMonitor;
    private static Socket client;
    private static boolean isOK = true;

    public static void main(String args[]) {
        connectToServer();
        getStreams();
        getName();
        if (isOK) {
            runDinner();
        } else {
            System.out.println("Philosofer could not connect to server.");
        }
    }

    private static void getName() {
        try {
            output.writeObject("Who am I?");
            output.flush();

            name = (String) input.readObject();
            if (name.contains("Success")) {
                name = name.replaceAll("Success. You are: ", "");
            } else {
                isOK = false;
            }
        } catch (Exception ex) {
            System.out.println("ERROR: " + ex.getMessage());
        }
    }

    public static void runDinner() {
        try {
            while (true) {
                postStatusMessage("Thinking");

                Thread.sleep(2000);

                postStatusMessage("Hungry");

                acquireChair();
                acquireLeftFork();
                acquireRightFork();

                postStatusMessage("Eating");

                Thread.sleep(2000);

                releaseLeftFork();
                releaseRightFork();
                releaseChair();
            }
        } catch (Exception ex) {
            System.out.println("ERROR: " + ex.getMessage());
        }
    }

    private static void postStatusMessage(String status) {
        //System.out.println(String.format("%s %s", name, message));
        try {
            output.writeObject(status);
            output.flush();
        } catch (Exception ex) {
            //MUAHAHAHA
        }
    }

    private static void acquireChair() {
        try {
            output.writeObject("P(chair)");
            output.flush();

            message = (String) input.readObject();
            if (!message.equalsIgnoreCase("Success")) {
                isOK = false;
            }
        } catch (Exception ex) {
            isOK = false;
        }
    }

    private static void acquireLeftFork() {
        try {
            output.writeObject("P(left)");
            output.flush();

            message = (String) input.readObject();
            if (!message.equalsIgnoreCase("Success")) {
                isOK = false;
            }
        } catch (Exception ex) {
            isOK = false;
        }
    }

    private static void acquireRightFork() {
        try {
            output.writeObject("P(right)");
            output.flush();

            message = (String) input.readObject();
            if (!message.equalsIgnoreCase("Success")) {
                isOK = false;
            }
        } catch (Exception ex) {
            isOK = false;
        }
    }

    private static void releaseChair() {
        try {
            output.writeObject("V(chair)");
            output.flush();

            message = (String) input.readObject();
            if (!message.equalsIgnoreCase("Success")) {
                isOK = false;
            }
        } catch (Exception ex) {
            isOK = false;
        }
    }

    private static void releaseLeftFork() {
        try {
            output.writeObject("V(left)");
            output.flush();

            message = (String) input.readObject();
            if (!message.equalsIgnoreCase("Success")) {
                isOK = false;
            }
        } catch (Exception ex) {
            isOK = false;
        }
    }

    private static void releaseRightFork() {
        try {
            output.writeObject("V(right)");
            output.flush();

            message = (String) input.readObject();
            if (!message.equalsIgnoreCase("Success")) {
                isOK = false;
            }
        } catch (Exception ex) {
            isOK = false;
        }
    }

    public static void connectToServer() {
        try {
            //wait 3 seconds just to make sure the server is ready to handle connections
            Thread.sleep(3000);
            client = new Socket(InetAddress.getByName(serverMonitor), 10000);
        } catch (Exception ex) {
            System.out.println("ERROR: " + ex.getMessage());
            isOK = false;
        }
    }

    private static void getStreams() {
        try {
            //configura o fluxo de saída
            output = new ObjectOutputStream(client.getOutputStream());
            output.flush();

            //configura o fluxo de entrada
            input = new ObjectInputStream(client.getInputStream());
        } catch (Exception ex) {
            System.out.println("ERROR: " + ex.getMessage());
        }
    }
}
